using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Zune.Forms
{
    /// <summary>
    /// Zune.Forms Control class.
    /// </summary>
    public class Control
    {
        #region Public Events/Delegates
        public delegate void OnControlTouched(object sender, GameTime gameTime, TouchLocation touch);
        public event OnControlTouched ControlTouched;
        public event OnControlTouched Clicked;
        public event OnControlTouched ControlTouchReleased;
        public event OnControlTouched GotFocus;
        public event OnControlTouched LostFocus;
        #endregion

        #region Private Members
        internal Vector2 _location = new Vector2(0, 0);
        internal Vector2 _size = new Vector2(10, 10);
        internal bool _visible = true;
        internal Color _backColor = Color.TransparentBlack;
        internal Color _foreColor = Color.Black;
        internal Form _form;
        internal Viewport _savedViewPort;
        internal List<Control> _controls = new List<Control>();
        internal bool _hasFocus = false;
        internal int _contextMenuDelay = 1000;
        internal Enumerations.BorderType _borderType = Enumerations.BorderType.BorderNone;
        internal Color _borderColor = Color.Black;
        internal Color _shadowBorderColor = Color.DarkGray;
        internal int _borderWidth = 1;
        internal bool _enabled = true;
        internal bool _wasAlreadyNotVisible = false;
        internal bool _canClick = true;
        internal Timer _clickTimer;
        internal bool _cantUpdate = false;
        #endregion

        #region Constructors
        /// <summary>
        /// Creates a new Control.
        /// </summary>
        /// <param name="form">The Form the control belongs to.</param>
        public Control(Form form)
        {
            _form = form;
            _form.Controls.Add(this);
            _clickTimer = new Timer(750);
            _clickTimer.Enabled = false;
            _clickTimer.Tick += new EventHandler(_clickTimer_Tick);
        }

        internal Control(Form form, bool isSystem)
        {
            _form = form;
            _form._sysControls.Add(this);
            _clickTimer = new Timer(750);
            _clickTimer.Enabled = false;
            _clickTimer.Tick += new EventHandler(_clickTimer_Tick);
        }

        public Control(Control owner)
        {
            _form = owner._form;
            owner._controls.Add(this);
            _clickTimer = new Timer(750);
            _clickTimer.Enabled = false;
            _clickTimer.Tick += new EventHandler(_clickTimer_Tick);
        }
        #endregion

        private void _clickTimer_Tick(object sender, EventArgs e)
        {
            _clickTimer.Enabled = false;
            _canClick = true;
        }


        #region Virtuals
        public virtual void LoadContent()
        {
            foreach (Control ctl in _controls)
                ctl.LoadContent();
        }

        internal void PreDraw()
        {
            if (_form != null)
            {
                Viewport vp = new Viewport();
                vp.X = (Int32)_location.X;
                vp.Y = (Int32)_location.Y;
                vp.Width = (Int32)_size.X;
                vp.Height = (Int32)_size.Y;
                _savedViewPort = GraphicsDevice.Viewport;
                GraphicsDevice.Viewport = vp;
            }
        }

        public virtual void Draw(GameTime gameTime)
        {
            if (_visible)
            {
                if (_form != null)
                {
                    switch (_borderType)
                    {
                        case Enumerations.BorderType.BorderSingle:
                            if (BackColor != Drawing.TransparentColor())
                                GraphicsDevice.Clear(BackColor);
                            break;
                        case Enumerations.BorderType.Border3D:
                            if (BackColor != Drawing.TransparentColor())
                                SpriteBatch.Draw(Drawing.CreateRectangle(GraphicsDevice, (Int32)_size.X - _borderWidth * 3, (Int32)_size.Y - _borderWidth * 3, BackColor), _location, Color.White);
                            break;
                        case Enumerations.BorderType.BorderNone:
                            if (BackColor != Drawing.TransparentColor())
                                GraphicsDevice.Clear(BackColor);
                            break;
                    }

                    foreach (Control ctl in _controls)
                    {
                       ctl.Draw(gameTime);
                       ctl._form.DrawBorder(ctl);
                    }
                }
            }
        }

        internal void PostDraw()
        {
            if (_form != null)
            {
                GraphicsDevice.Viewport = _savedViewPort;
            }
        }

        public virtual void Update(GameTime gameTime, TouchCollection touches)
        {
            if (_visible && _enabled)
            {
                foreach (TouchLocation touch in touches)
                {
                    if (Utilities.IsControlTouched(touch.Position, _location, _size))
                    {
                        switch (touch.State)
                        {
                            case TouchLocationState.Moved:
                            case TouchLocationState.Pressed:
                                if (ControlTouched != null)
                                    ControlTouched(this, gameTime, touch);

                                if (GotFocus != null)
                                    GotFocus(this, gameTime, touch);

                                _hasFocus = true;
                                break;
                            case TouchLocationState.Released:
                                if (ControlTouchReleased != null)
                                    ControlTouchReleased(this, gameTime, touch);

                                if (Utilities.IsControlClicked(touch, _location, _size) && _canClick)
                                {
                                    if (Clicked != null)
                                        Clicked(this, gameTime, touch);
                                    
                                }

                                break;
                        }
                    }
                    else
                    {
                        if (_hasFocus)
                        {
                            if (LostFocus != null)
                                LostFocus(this, gameTime, touch);
                        }

                        _hasFocus = false;
                    }
                }

                foreach (Control ctl in _controls)
                    ctl.Update(gameTime, touches);
            }
            else
            {
                if (_hasFocus)
                {
                    if (LostFocus != null)
                        LostFocus(this, gameTime, new TouchLocation());
                }
                _hasFocus = false;
            }
        }
        #endregion

        #region Public Properties
        public bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }

        public Enumerations.BorderType BorderType
        {
            get { return _borderType; }
            set { _borderType = value; }
        }

        /// <summary>
        /// Gets the Form (owner) of the control.
        /// </summary>
        public Form Form
        {
            get { return _form; }
        }

        /// <summary>
        /// Gets the SpriteBatch to use for drawing.
        /// </summary>
        public SpriteBatch SpriteBatch
        {
            get 
            {
                if (_form != null)
                    return _form.SpriteBatch;
                else
                    return null;
            }
        }

        /// <summary>
        /// Gets the GraphicsDevice.
        /// </summary>
        public GraphicsDevice GraphicsDevice
        {
            get 
            {
                if (_form != null)
                    return _form.GraphicsDevice;
                else
                    return null;
            }
        }

        /// <summary>
        /// Gets or sets the location of the control.
        /// </summary>
        public Vector2 Location
        {
            get { return _location; }
            set { _location = value; }
        }

        /// <summary>
        /// Gets or sets the size of the control.
        /// </summary>
        public Vector2 Size
        {
            get { return _size; }
            set { _size = value; }
        }

        /// <summary>
        /// Gets or sets the Color to use as BackColor
        /// </summary>
        public Color BackColor
        {
            get { return _backColor; }
            set { _backColor = value; }
        }

        /// <summary>
        /// Gets or sets the Color to use as ForeColor
        /// </summary>
        public Color ForeColor
        {
            get { return _foreColor; }
            set { _foreColor = value; }
        }

        /// <summary>
        /// Gets or sets whether the Control is visible.
        /// </summary>
        public bool Visible
        {
            get { return _visible; }
            set 
            {
                if (!_visible && value)
                    _cantUpdate = true;

                _visible = value;

                if (!value)
                {
                    _canClick = false;
                }
                else
                {
                    _clickTimer.Enabled = true;
                }

                foreach (Control ctl in _controls)
                {
                    if (!value && !ctl.Visible)
                    {
                        ctl._wasAlreadyNotVisible = true;
                        ctl.Visible = _visible;
                    }
                    else if (value && !ctl._wasAlreadyNotVisible)
                    {
                        ctl.Visible = _visible;
                    }
                    else if (value && ctl._wasAlreadyNotVisible)
                    {
                        ctl._wasAlreadyNotVisible = false;
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the Controls this Control owns.
        /// </summary>
        public List<Control> Controls
        {
            get { return _controls; }
            set { _controls = value; }
        }

        /// <summary>
        /// Gets the Top of the Control.
        /// </summary>
        public float Top
        {
            get { return _location.Y; }
        }

        /// <summary>
        /// Gets the Bottom of the Control.
        /// </summary>
        public float Bottom
        {
            get { return _location.Y + _size.Y; }
        }

        /// <summary>
        /// Gets the Left of the Control.
        /// </summary>
        public float Left
        {
            get { return _location.X; }
        }

        /// <summary>
        /// Gets the Right of the Control.
        /// </summary>
        public float Right
        {
            get { return _location.X + _size.X; }
        }

        /// <summary>
        /// Gets whether the Control has focus or not, true/false.
        /// </summary>
        public bool HasFocus
        {
            get { return _hasFocus; }
        }
        #endregion
    }
}